->tell how many outstanding acknowledgements there are
EXPORT PROC howManyAcksLeft() OF rxcom
RETURN self.unconfirmed
ENDPROC
->wait for an ARexx message with a real command, and returns that command and/or notification of a Ctrl-C
EXPORT PROC waitForRexxMsg(tellofack=FALSE) OF rxcom
DEF signalmask=0, hostmask=0, command=NIL:PTR TO CHAR, args=NIL:PTR TO CHAR,
rexxmsg=NIL:PTR TO rexxmsg,
quit=FALSE, busywait=TRUE, ->note we never REALLY "busy wait" if busywait=TRUE - but we DO directly poll the list until it is empty
wasack=FALSE
hostmask:=Shl(1,self.hostport.sigbit) ->signalmask for our host port
IF self.cmdtoreply=NIL
/* get a valid command to be returned for the host */
REPEAT
IF busywait ->see if there's a good chance of another message (i.e.we just got one before) then...
->...directly poll for another message, else...
rexxmsg:=GetMsg(self.hostport) ->(try to) get next message
IF rexxmsg ->see if there really was a message
command, args, wasack:=self.handleRexxMsg({rexxmsg}) ->handle this message
ELSE
busywait:=FALSE ->no more messages currently in list, so don't busywait!
ENDIF
ELSE
->...get OS to wake us when a new message arrives
signalmask:=Wait(hostmask OR SIGBREAKF_CTRL_C) ->wait for event signals (either message for us or a Ctrl-C)
IF signalmask AND hostmask ->act on a message signal
rexxmsg:=GetMsg(self.hostport) ->get first message
command, args, wasack:=self.handleRexxMsg({rexxmsg}) ->handle this event
ENDIF
IF signalmask AND SIGBREAKF_CTRL_C THEN quit:=TRUE ->act on a quit signal
ENDIF
UNTIL command OR quit OR (wasack AND tellofack) ->repeat if last message was a confirmation reply to a message from us, unless caller wants to know about it
IF wasack AND tellofack ->if msg was just an acknowledge then...
command:=NIL ->...ensure caller can't read any useless info...
args:=NIL
ELSE ->...else store valid message (so know this needs acknolwedging)
self.rexxmsgtoreply:=rexxmsg ->store rexxmsg (pointer) for replyToRexxMsg()
self.argstoreply:=args ->record of String() to DisposeLink() of
self.cmdtoreply:=command ->show that stored rexxmsg not yet replied to (& record of String() to DisposeLink() of)
ENDIF
IF quit AND command THEN WriteF('WARNING: waitForRexxMsg(); Ctrl-C & a command recieved simultaneously; was assumed impossible, so Ctrl-C has been safely ignored. Please notify author of ARexxComm (Chris.S.Handley@BTInternet.com).\n') ->should never happen (I guess)
ELSE
Throw("RXNA",self.cmdtoreply) ->error: didn't reply to last message!
ENDIF
ENDPROC command, args, wasack
->poll for an ARexx message with a real command, and returns that command (may =NIL)
EXPORT PROC pollForRexxMsg(tellofack=FALSE) OF rxcom
DEF hostmask=0, command=NIL:PTR TO CHAR, args=NIL:PTR TO CHAR,
rexxmsg=NIL:PTR TO rexxmsg, old_rexxmsg=NIL:PTR TO rexxmsg,
wasack=FALSE
hostmask:=Shl(1,self.hostport.sigbit) ->signalmask for our host port
IF self.cmdtoreply=NIL
/* get a valid command to be returned for the host, if one exists */
REPEAT
/* directly poll for a message */
rexxmsg:=GetMsg(self.hostport) ->(try to) get next message
old_rexxmsg:=rexxmsg
IF rexxmsg ->see if there really was a message
command, args, wasack:=self.handleRexxMsg({rexxmsg}) ->handle this message
ENDIF
UNTIL (rexxmsg=old_rexxmsg) OR (wasack AND tellofack) ->repeat if last message was a confirmation reply to a message from us, unless caller wants to know about it
IF wasack AND tellofack ->if msg was just an acknowledge then...
command:=NIL ->...ensure caller can't read any useless info...
args:=NIL
ELSE ->...else store valid message (so know this needs acknolwedging)
self.rexxmsgtoreply:=rexxmsg ->store rexxmsg (pointer) for replyToRexxMsg()
self.argstoreply:=args ->record of String() to DisposeLink() of
self.cmdtoreply:=command ->show that stored rexxmsg not yet replied to (& record of String() to DisposeLink() of)
ENDIF
ELSE
Throw("RXNA",self.cmdtoreply) ->error: didn't reply to last message!
ENDIF
ENDPROC command, args, wasack
->examine message & deal with if was a reply to something we sent (& nullify rexxmsg since was dealt with), else return command
PROC handleRexxMsg(rexxmsgptr:PTR TO LONG) OF rxcom ->rexxmsgptr=address of pointer to handled message
DEF rexxmsg=NIL:PTR TO rexxmsg,->pointer to handled message; dereferenced rexxmsgptr
msgnode:PTR TO mn, ->pointer to messagenode
listnode:PTR TO ln, ->pointer to listnode of message
rexxargs:PTR TO LONG, ->list of 16 argument pointers (inc.command strings)
command=NIL:PTR TO CHAR, ->points to command string
args=NIL:PTR TO CHAR, ->points to arguments string
wasack=FALSE, ->says whether message was an acknowledgement of our message or not
cmdstart, cmdend, argsstart, argsend, string:PTR TO CHAR
rexxmsg:=^rexxmsgptr
IF rexxmsg ->could be called with no message to handle! (don't think should ever happen, but...)
msgnode:=rexxmsg.mn ->get pointer to messagenode
listnode:=msgnode.ln ->get pointer to listnode
rexxargs:=rexxmsg.args ->get pointer to commands
IF listnode.type=NT_REPLYMSG ->if confirmation reply of a message sent by us then...
->...deal automatically with our reply...
IF rexxargs[15] ->see if this is a reply to a forwarded message then...
ReplyMsg(rexxargs[15]) ->...finally reply to original sender that message was handled
->send a message to some target ARexx port - with an Added pointer as the last argument
PROC sendRexxMsg_Add(targetname:PTR TO CHAR, command:PTR TO CHAR, unknownmsg=NIL, flags=0) OF rxcom
DEF targetport=NIL:PTR TO mp, rexxmsg=NIL:PTR TO rexxmsg, rexxargs=NIL:PTR TO LONG, hostport=NIL:PTR TO mp,
listnode=NIL:PTR TO ln, argstring=NIL, cmdlen
IF targetname=NIL THEN Throw("RXCM",'sendRexxMsg_Add(); targetname was NIL')
IF command=NIL THEN Throw("RXCM",'sendRexxMsg_Add(); command was NIL')
hostport:=self.hostport
listnode:=hostport.ln
IF (rexxmsg:=CreateRexxMsg(hostport,'rexx',listnode.name))=NIL THEN RETURN NIL ->tell if could not send message; N.B.CreateRexxMsg() sets .replyport for us
rexxargs:=rexxmsg.args ->pointer to commands
cmdlen:=StrLen(command)
IF argstring:=CreateArgstring(command,cmdlen+3) ->was the argstring created?
argstring[cmdlen]:="\0" ->ensure null terminated!
rexxargs[0]:=argstring ->set the first argstring
rexxmsg.action:=RXCOMM OR flags ->set the flags
rexxargs[15]:=unknownmsg ->store original message pointer into 16th argstring pointer for handleRexxMsg()
Forbid() ->forbid multitasking (ouch!)
IF (targetport:=FindPort(targetname)) THEN PutMsg(targetport,rexxmsg) ->send our message to an existing port
Permit() ->permit multitasking (phew!)
IF targetport ->check if message was sent
IF unknownmsg=NIL THEN self.unconfirmed:=self.unconfirmed+1 ->increase the unconfirmed message-recieved counter (for messages sent by user)